#!/usr/bin/env node

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

/**
 * 信号胜率统计脚本
 * 分析 trades.json 中的交易数据，统计每种信号的胜率
 * 胜利条件：rp > 0
 * 支持按信号类型和时间维度（日期、小时、星期）进行统计
 */

// 读取交易数据
function loadTradesData(filePath) {
    let tradesFilePath;
    
    if (filePath) {
        // 如果提供了文件路径，使用该路径
        tradesFilePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
    } else {
        // 默认使用项目根目录下的 trades.json
        tradesFilePath = path.join(__dirname, '../trades.json');
    }
    
    try {
        const data = fs.readFileSync(tradesFilePath, 'utf8');
        const tradesData = JSON.parse(data);
        return {
            data: tradesData.history || [],
            filePath: tradesFilePath
        };
    } catch (error) {
        console.error(`读取交易数据失败 (${tradesFilePath}):`, error.message);
        return {
            data: [],
            filePath: tradesFilePath
        };
    }
}

// 提取信号文本，去除动态参数保持信号类型的一致性
function normalizeSignal(signalText) {
    if (!signalText) return 'unknown';
    
    // 将信号文本标准化
    let normalized = signalText.toLowerCase();
    
    // 归类常见的信号类型
    if (normalized.includes('多头信号') || normalized.includes('多头机会')) {
        return 'bull_signal';
    } else if (normalized.includes('空头信号') || normalized.includes('空头预警') || normalized.includes('超买')) {
        return 'bear_signal';  
    } else if (normalized.includes('等待信号') || normalized.includes('双kd方向不明确')) {
        return 'wait_signal';
    } else if (normalized.includes('可能超卖')) {
        return 'oversold_signal';
    } else if (normalized.includes('无明显信号')) {
        return 'no_signal';
    } else {
        return 'other_signal';
    }
}

// 分析信号胜率
function analyzeSignalWinRate(trades) {
    const signalStats = {};
    
    trades.forEach(trade => {
        const rp = parseFloat(trade.rp || 0);
        const signal = trade.data?.signal?.signal || 'unknown';
        const normalizedSignal = normalizeSignal(signal);
        
        // 初始化统计数据
        if (!signalStats[normalizedSignal]) {
            signalStats[normalizedSignal] = {
                signalType: normalizedSignal,
                totalTrades: 0,
                winTrades: 0,
                lossTrades: 0,
                totalProfit: 0,
                avgProfit: 0,
                winRate: 0,
                maxProfit: -Infinity,
                minProfit: Infinity,
                examples: []
            };
        }
        
        const stat = signalStats[normalizedSignal];
        stat.totalTrades++;
        stat.totalProfit += rp;
        
        // 判断是否为胜利交易（rp > 0）
        if (rp > 0) {
            stat.winTrades++;
        } else {
            stat.lossTrades++;
        }
        
        // 记录最大最小收益
        stat.maxProfit = Math.max(stat.maxProfit, rp);
        stat.minProfit = Math.min(stat.minProfit, rp);
        
        // 保存原始信号示例（最多5个）
        if (stat.examples.length < 5) {
            stat.examples.push({
                symbol: trade.symbol,
                rp: rp,
                signal: signal,
                time: trade.data?.time || 'unknown'
            });
        }
    });
    
    // 计算统计数据
    Object.values(signalStats).forEach(stat => {
        stat.winRate = stat.totalTrades > 0 ? (stat.winTrades / stat.totalTrades * 100) : 0;
        stat.avgProfit = stat.totalTrades > 0 ? (stat.totalProfit / stat.totalTrades) : 0;
        
        // 修复最大最小收益的无穷大值
        if (stat.maxProfit === -Infinity) stat.maxProfit = 0;
        if (stat.minProfit === Infinity) stat.minProfit = 0;
    });
    
    return signalStats;
}

// 按时间分析统计
function analyzeByTime(trades) {
    const timeStats = {
        byDate: {},
        byHour: {},
        byWeekday: {}
    };
    
    const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
    
    trades.forEach(trade => {
        const rp = parseFloat(trade.rp || 0);
        const timeStr = trade.data?.time;
        
        if (!timeStr || timeStr === 'unknown') return;
        
        try {
            const date = new Date(timeStr);
            if (isNaN(date.getTime())) return;
            
            const dateKey = date.toISOString().split('T')[0]; // YYYY-MM-DD
            const hour = date.getHours();
            const weekday = weekdays[date.getDay()];
            
            // 按日期统计
            if (!timeStats.byDate[dateKey]) {
                timeStats.byDate[dateKey] = {
                    date: dateKey,
                    totalTrades: 0,
                    winTrades: 0,
                    totalProfit: 0,
                    avgProfit: 0,
                    winRate: 0
                };
            }
            
            const dateStat = timeStats.byDate[dateKey];
            dateStat.totalTrades++;
            dateStat.totalProfit += rp;
            if (rp > 0) dateStat.winTrades++;
            
            // 按小时统计
            if (!timeStats.byHour[hour]) {
                timeStats.byHour[hour] = {
                    hour: hour,
                    totalTrades: 0,
                    winTrades: 0,
                    totalProfit: 0,
                    avgProfit: 0,
                    winRate: 0
                };
            }
            
            const hourStat = timeStats.byHour[hour];
            hourStat.totalTrades++;
            hourStat.totalProfit += rp;
            if (rp > 0) hourStat.winTrades++;
            
            // 按星期统计
            if (!timeStats.byWeekday[weekday]) {
                timeStats.byWeekday[weekday] = {
                    weekday: weekday,
                    totalTrades: 0,
                    winTrades: 0,
                    totalProfit: 0,
                    avgProfit: 0,
                    winRate: 0
                };
            }
            
            const weekdayStat = timeStats.byWeekday[weekday];
            weekdayStat.totalTrades++;
            weekdayStat.totalProfit += rp;
            if (rp > 0) weekdayStat.winTrades++;
            
        } catch (error) {
            // 忽略时间解析错误
        }
    });
    
    // 计算统计数据
    Object.values(timeStats.byDate).forEach(stat => {
        stat.winRate = stat.totalTrades > 0 ? (stat.winTrades / stat.totalTrades * 100) : 0;
        stat.avgProfit = stat.totalTrades > 0 ? (stat.totalProfit / stat.totalTrades) : 0;
    });
    
    Object.values(timeStats.byHour).forEach(stat => {
        stat.winRate = stat.totalTrades > 0 ? (stat.winTrades / stat.totalTrades * 100) : 0;
        stat.avgProfit = stat.totalTrades > 0 ? (stat.totalProfit / stat.totalTrades) : 0;
    });
    
    Object.values(timeStats.byWeekday).forEach(stat => {
        stat.winRate = stat.totalTrades > 0 ? (stat.winTrades / stat.totalTrades * 100) : 0;
        stat.avgProfit = stat.totalTrades > 0 ? (stat.totalProfit / stat.totalTrades) : 0;
    });
    
    return timeStats;
}

// 格式化输出结果
function formatResults(signalStats, filePath) {
    console.log('\n=== 信号胜率统计报告 ===');
    console.log(`文件路径: ${filePath}`);
    console.log(`统计时间: ${new Date().toLocaleString()}`);
    console.log(`胜利条件: rp > 0\n`);
    
    // 按胜率排序
    const sortedStats = Object.values(signalStats).sort((a, b) => b.winRate - a.winRate);
    
    console.log('信号类型'.padEnd(20) + '总交易'.padEnd(10) + '胜利'.padEnd(8) + '失败'.padEnd(8) + '胜率'.padEnd(10) + '平均收益'.padEnd(12) + '最大收益'.padEnd(12) + '最小收益');
    console.log('-'.repeat(100));
    
    sortedStats.forEach(stat => {
        const signalName = getSignalDisplayName(stat.signalType);
        console.log(
            signalName.padEnd(20) +
            stat.totalTrades.toString().padEnd(10) +
            stat.winTrades.toString().padEnd(8) +
            stat.lossTrades.toString().padEnd(8) +
            `${stat.winRate.toFixed(1)}%`.padEnd(10) +
            stat.avgProfit.toFixed(4).padEnd(12) +
            stat.maxProfit.toFixed(4).padEnd(12) +
            stat.minProfit.toFixed(4)
        );
    });
    
    // 显示详细示例
    console.log('\n=== 信号示例 ===');
    sortedStats.forEach(stat => {
        if (stat.examples.length > 0) {
            console.log(`\n${getSignalDisplayName(stat.signalType)}:`);
            stat.examples.forEach((example, index) => {
                console.log(`  ${index + 1}. ${example.symbol} - rp: ${example.rp} - ${example.signal} (${example.time})`);
            });
        }
    });
    
    // 总体统计
    const totalTrades = sortedStats.reduce((sum, stat) => sum + stat.totalTrades, 0);
    const totalWins = sortedStats.reduce((sum, stat) => sum + stat.winTrades, 0);
    const totalProfit = sortedStats.reduce((sum, stat) => sum + stat.totalProfit, 0);
    
    console.log('\n=== 总体统计 ===');
    console.log(`总交易数: ${totalTrades}`);
    console.log(`总胜利数: ${totalWins}`);
    console.log(`总体胜率: ${totalTrades > 0 ? (totalWins / totalTrades * 100).toFixed(2) : 0}%`);
    console.log(`总体盈亏: ${totalProfit.toFixed(4)}`);
    console.log(`平均收益: ${totalTrades > 0 ? (totalProfit / totalTrades).toFixed(4) : 0}`);
}

// 格式化时间统计输出结果
function formatTimeResults(timeStats) {
    console.log('\n=== 按时间维度统计 ===');
    
    // 按日期统计
    if (Object.keys(timeStats.byDate).length > 0) {
        console.log('\n--- 按日期统计 ---');
        const dateStats = Object.values(timeStats.byDate).sort((a, b) => a.date.localeCompare(b.date));
        
        console.log('日期        '.padEnd(15) + '交易数'.padEnd(8) + '胜利数'.padEnd(8) + '胜率'.padEnd(10) + '总盈亏'.padEnd(12) + '平均收益');
        console.log('-'.repeat(65));
        
        dateStats.forEach(stat => {
            console.log(
                stat.date.padEnd(15) +
                stat.totalTrades.toString().padEnd(8) +
                stat.winTrades.toString().padEnd(8) +
                `${stat.winRate.toFixed(1)}%`.padEnd(10) +
                stat.totalProfit.toFixed(4).padEnd(12) +
                stat.avgProfit.toFixed(4)
            );
        });
    }
    
    // 按小时统计
    if (Object.keys(timeStats.byHour).length > 0) {
        console.log('\n--- 按小时统计 ---');
        const hourStats = Object.values(timeStats.byHour).sort((a, b) => a.hour - b.hour);
        
        console.log('时间段      '.padEnd(12) + '交易数'.padEnd(8) + '胜利数'.padEnd(8) + '胜率'.padEnd(10) + '总盈亏'.padEnd(12) + '平均收益');
        console.log('-'.repeat(62));
        
        hourStats.forEach(stat => {
            const timeRange = `${stat.hour.toString().padStart(2, '0')}:00-${((stat.hour + 1) % 24).toString().padStart(2, '0')}:00`;
            console.log(
                timeRange.padEnd(12) +
                stat.totalTrades.toString().padEnd(8) +
                stat.winTrades.toString().padEnd(8) +
                `${stat.winRate.toFixed(1)}%`.padEnd(10) +
                stat.totalProfit.toFixed(4).padEnd(12) +
                stat.avgProfit.toFixed(4)
            );
        });
    }
    
    // 按星期统计
    if (Object.keys(timeStats.byWeekday).length > 0) {
        console.log('\n--- 按星期统计 ---');
        const weekdayOrder = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
        const weekdayStats = weekdayOrder
            .map(day => timeStats.byWeekday[day])
            .filter(stat => stat);
        
        console.log('星期        '.padEnd(12) + '交易数'.padEnd(8) + '胜利数'.padEnd(8) + '胜率'.padEnd(10) + '总盈亏'.padEnd(12) + '平均收益');
        console.log('-'.repeat(62));
        
        weekdayStats.forEach(stat => {
            console.log(
                stat.weekday.padEnd(12) +
                stat.totalTrades.toString().padEnd(8) +
                stat.winTrades.toString().padEnd(8) +
                `${stat.winRate.toFixed(1)}%`.padEnd(10) +
                stat.totalProfit.toFixed(4).padEnd(12) +
                stat.avgProfit.toFixed(4)
            );
        });
    }
    
    // 最佳时间段推荐
    console.log('\n--- 时间段表现排序 ---');
    
    if (Object.keys(timeStats.byHour).length > 0) {
        const topHours = Object.values(timeStats.byHour)
            .filter(stat => stat.totalTrades >= 2) // 至少2笔交易
            .sort((a, b) => b.winRate - a.winRate)
            .slice(0, 5);
            
        if (topHours.length > 0) {
            console.log('\n胜率最高的时间段（至少2笔交易）：');
            topHours.forEach((stat, index) => {
                const timeRange = `${stat.hour.toString().padStart(2, '0')}:00-${((stat.hour + 1) % 24).toString().padStart(2, '0')}:00`;
                console.log(`${index + 1}. ${timeRange} - 胜率: ${stat.winRate.toFixed(1)}% (${stat.winTrades}/${stat.totalTrades})`);
            });
        }
    }
    
    if (Object.keys(timeStats.byWeekday).length > 0) {
        const topWeekdays = Object.values(timeStats.byWeekday)
            .filter(stat => stat.totalTrades >= 2) // 至少2笔交易
            .sort((a, b) => b.winRate - a.winRate);
            
        if (topWeekdays.length > 0) {
            console.log('\n胜率最高的星期（至少2笔交易）：');
            topWeekdays.forEach((stat, index) => {
                console.log(`${index + 1}. ${stat.weekday} - 胜率: ${stat.winRate.toFixed(1)}% (${stat.winTrades}/${stat.totalTrades})`);
            });
        }
    }
}

// 获取信号显示名称
function getSignalDisplayName(signalType) {
    const nameMap = {
        'bull_signal': '多头信号',
        'bear_signal': '空头信号',
        'wait_signal': '等待信号',
        'oversold_signal': '超卖信号',
        'no_signal': '无明显信号',
        'other_signal': '其他信号',
        'unknown': '未知信号'
    };
    return nameMap[signalType] || signalType;
}

// 显示使用说明
function showUsage() {
    console.log('使用说明:');
    console.log('  node scripts/signal-stats.js [文件路径]');
    console.log('');
    console.log('参数:');
    console.log('  文件路径  - 可选，指定要分析的订单文件路径');
    console.log('              如果不提供，默认使用 ./trades.json');
    console.log('');
    console.log('示例:');
    console.log('  node scripts/signal-stats.js                    # 使用默认文件');
    console.log('  node scripts/signal-stats.js trades.json        # 使用相对路径');
    console.log('  node scripts/signal-stats.js /path/to/data.json # 使用绝对路径');
    console.log('');
}

// 主函数
function main() {
    const args = process.argv.slice(2);
    
    // 检查是否请求帮助
    if (args.includes('-h') || args.includes('--help')) {
        showUsage();
        return;
    }
    
    const filePath = args[0]; // 获取第一个参数作为文件路径
    
    console.log('开始分析信号胜率...\n');
    
    const result = loadTradesData(filePath);
    const { data: trades, filePath: actualFilePath } = result;
    
    if (trades.length === 0) {
        console.log('没有找到交易数据或文件为空');
        if (filePath) {
            console.log('请检查文件路径是否正确');
        }
        return;
    }
    
    console.log(`文件路径: ${actualFilePath}`);
    console.log(`加载了 ${trades.length} 条交易记录`);
    
    const signalStats = analyzeSignalWinRate(trades);
    const timeStats = analyzeByTime(trades);
    
    formatResults(signalStats, actualFilePath);
    formatTimeResults(timeStats);
}

// 执行分析
if (import.meta.url === `file://${process.argv[1]}`) {
    main();
}